package com.kexio.pay.provider;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import org.springframework.util.StringUtils;
import com.kexio.pay.config.AliPayProperties;
import com.kexio.pay.dto.PaymentRequest;
import com.kexio.pay.dto.PaymentResponse;
import com.kexio.pay.entity.PaymentCallback;
import com.kexio.pay.enums.PaymentMethod;
import com.kexio.pay.enums.PaymentStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 支付宝支付提供者（使用支付宝官方SDK）
 * 
 * @author Kexio Team
 */
@Component
public class AliPayProvider implements PaymentProvider {
    
    private static final Logger logger = LoggerFactory.getLogger(AliPayProvider.class);
    private static final String PROVIDER_ID = "alipay";
    private static final String PROVIDER_NAME = "支付宝";
    
    @Autowired
    private AliPayProperties aliPayProperties;
    
    private AlipayClient alipayClient;
    
    /**
     * 获取或初始化支付宝客户端
     */
    private synchronized AlipayClient getAlipayClient() {
        if (alipayClient == null) {
            logger.info("=== 初始化支付宝客户端 ===");
            logger.info("AppId: {}", aliPayProperties.getAppId());
            logger.info("网关地址: {}", aliPayProperties.getServerUrl());
            logger.info("字符集: {}", aliPayProperties.getCharset());
            logger.info("签名类型: {}", aliPayProperties.getSignType());
            logger.info("数据格式: {}", aliPayProperties.getFormat());
            logger.info("回调域名: {}", aliPayProperties.getDomain());
            logger.info("应用私钥长度: {}", aliPayProperties.getPrivateKey() != null ? aliPayProperties.getPrivateKey().length() : 0);
            logger.info("支付宝公钥长度: {}", aliPayProperties.getPublicKey() != null ? aliPayProperties.getPublicKey().length() : 0);
            logger.info("===========================");
            
            try {
                // 使用 AlipayConfig 对象方式初始化（官方推荐）
                AlipayConfig alipayConfig = new AlipayConfig();
                alipayConfig.setServerUrl(aliPayProperties.getServerUrl());
                alipayConfig.setAppId(aliPayProperties.getAppId());
                alipayConfig.setPrivateKey(aliPayProperties.getPrivateKey());
                alipayConfig.setFormat(aliPayProperties.getFormat());
                alipayConfig.setAlipayPublicKey(aliPayProperties.getPublicKey());
                alipayConfig.setCharset(aliPayProperties.getCharset());
                alipayConfig.setSignType(aliPayProperties.getSignType());
                
                alipayClient = new DefaultAlipayClient(alipayConfig);
                
                logger.info("✅ 支付宝客户端初始化成功");
            } catch (AlipayApiException e) {
                logger.error("❌ 支付宝客户端初始化失败", e);
                throw new RuntimeException("支付宝客户端初始化失败", e);
            }
        }
        return alipayClient;
    }
    
    @Override
    public String getProviderId() {
        return PROVIDER_ID;
    }
    
    @Override
    public String getProviderName() {
        return PROVIDER_NAME;
    }
    
    @Override
    public Set<PaymentMethod> getSupportedMethods() {
        Set<PaymentMethod> methods = new HashSet<>();
        methods.add(PaymentMethod.ALIPAY_PC);      // PC网站支付
        methods.add(PaymentMethod.ALIPAY_WAP);     // 手机网站支付
        methods.add(PaymentMethod.ALIPAY_APP);     // APP支付
        methods.add(PaymentMethod.ALIPAY_QR);      // 扫码支付
        return methods;
    }
    
    @Override
    public boolean isSupported(PaymentMethod method) {
        return getSupportedMethods().contains(method);
    }
    
    @Override
    public PaymentResponse createPayment(PaymentRequest request) {
        try {
            PaymentMethod method = PaymentMethod.fromCode(request.getPaymentMethod());
            logger.info("创建支付宝订单: orderNo={}, amount={}, method={}", 
                       request.getOrderNo(), request.getAmount(), method.getDescription());
            
            // 根据支付方式调用不同的API
            switch (method) {
                case ALIPAY_PC:
                    return createPcPayment(request);
                case ALIPAY_WAP:
                    return createWapPayment(request);
                case ALIPAY_APP:
                    return createAppPayment(request);
                case ALIPAY_QR:
                    return createQrPayment(request);
                default:
                    return createErrorResponse(request.getOrderNo(), "不支持的支付方式: " + method);
            }
            
        } catch (Exception e) {
            logger.error("创建支付宝订单异常: orderNo={}", request.getOrderNo(), e);
            return createErrorResponse(request.getOrderNo(), "创建订单失败: " + e.getMessage());
        }
    }
    
    /**
     * PC网站支付 (alipay.trade.page.pay)
     */
    private PaymentResponse createPcPayment(PaymentRequest request) throws AlipayApiException {
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(request.getOrderNo());
        model.setTotalAmount(request.getAmount().setScale(2).toString());
        model.setSubject(request.getSubject());
        model.setBody(request.getBody());
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setBizModel(model);
        String notifyUrl = aliPayProperties.getDomain() + "/api/forum/payment/alipay/notify";
        String returnUrl = aliPayProperties.getDomain() + "/payment/return";
        alipayRequest.setNotifyUrl(notifyUrl);
        alipayRequest.setReturnUrl(returnUrl);
        
        // 打印调用参数
        logger.info("=== 支付宝PC支付参数 ===");
        logger.info("订单号: {}", request.getOrderNo());
        logger.info("金额: {}", model.getTotalAmount());
        logger.info("标题: {}", model.getSubject());
        logger.info("描述: {}", model.getBody());
        logger.info("产品码: {}", model.getProductCode());
        logger.info("通知地址: {}", notifyUrl);
        logger.info("返回地址: {}", returnUrl);
        logger.info("AppId: {}", aliPayProperties.getAppId());
        logger.info("网关: {}", aliPayProperties.getServerUrl());
        logger.info("签名类型: {}", aliPayProperties.getSignType());
        logger.info("字符集: {}", aliPayProperties.getCharset());
        logger.info("格式: {}", aliPayProperties.getFormat());
        logger.info("========================");
        
        AlipayTradePagePayResponse response = getAlipayClient().pageExecute(alipayRequest);
        
        if (response.isSuccess()) {
            logger.info("支付宝PC支付创建成功: orderNo={}", request.getOrderNo());
            
            PaymentResponse paymentResponse = new PaymentResponse();
            paymentResponse.setSuccess(true);
            paymentResponse.setOrderNo(request.getOrderNo());
            paymentResponse.setPaymentUrl(response.getBody()); // 返回form表单HTML
            paymentResponse.setMessage("订单创建成功");
            return paymentResponse;
        } else {
            logger.error("支付宝PC支付创建失败: orderNo={}, code={}, msg={}", 
                        request.getOrderNo(), response.getCode(), response.getMsg());
            return createErrorResponse(request.getOrderNo(), response.getMsg());
        }
    }
    
    /**
     * 手机网站支付 (alipay.trade.wap.pay)
     */
    private PaymentResponse createWapPayment(PaymentRequest request) throws AlipayApiException {
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(request.getOrderNo());
        model.setTotalAmount(request.getAmount().setScale(2).toString());
        model.setSubject(request.getSubject());
        model.setBody(request.getBody());
        model.setProductCode("QUICK_WAP_WAY");
        
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        alipayRequest.setBizModel(model);
        String notifyUrl = aliPayProperties.getDomain() + "/api/forum/payment/alipay/notify";
        String returnUrl = aliPayProperties.getDomain() + "/payment/return";
        alipayRequest.setNotifyUrl(notifyUrl);
        alipayRequest.setReturnUrl(returnUrl);
        
        // 打印调用参数
        logger.info("=== 支付宝WAP支付参数 ===");
        logger.info("订单号: {}", request.getOrderNo());
        logger.info("金额: {}", model.getTotalAmount());
        logger.info("标题: {}", model.getSubject());
        logger.info("描述: {}", model.getBody());
        logger.info("产品码: {}", model.getProductCode());
        logger.info("通知地址: {}", notifyUrl);
        logger.info("返回地址: {}", returnUrl);
        logger.info("========================");
        
        AlipayTradeWapPayResponse response = getAlipayClient().pageExecute(alipayRequest);
        
        if (response.isSuccess()) {
            logger.info("支付宝WAP支付创建成功: orderNo={}", request.getOrderNo());
            
            PaymentResponse paymentResponse = new PaymentResponse();
            paymentResponse.setSuccess(true);
            paymentResponse.setOrderNo(request.getOrderNo());
            paymentResponse.setPaymentUrl(response.getBody());
            paymentResponse.setMessage("订单创建成功");
            return paymentResponse;
        } else {
            logger.error("支付宝WAP支付创建失败: orderNo={}, code={}, msg={}", 
                        request.getOrderNo(), response.getCode(), response.getMsg());
            return createErrorResponse(request.getOrderNo(), response.getMsg());
        }
    }
    
    /**
     * APP支付 (alipay.trade.app.pay)
     */
    private PaymentResponse createAppPayment(PaymentRequest request) throws AlipayApiException {
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setOutTradeNo(request.getOrderNo());
        model.setTotalAmount(request.getAmount().setScale(2).toString());
        model.setSubject(request.getSubject());
        model.setBody(request.getBody());
        model.setProductCode("QUICK_MSECURITY_PAY");
        
        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        alipayRequest.setBizModel(model);
        String notifyUrl = aliPayProperties.getDomain() + "/api/forum/payment/alipay/notify";
        alipayRequest.setNotifyUrl(notifyUrl);
        
        // 打印调用参数
        logger.info("=== 支付宝APP支付参数 ===");
        logger.info("订单号: {}", request.getOrderNo());
        logger.info("金额: {}", model.getTotalAmount());
        logger.info("标题: {}", model.getSubject());
        logger.info("描述: {}", model.getBody());
        logger.info("产品码: {}", model.getProductCode());
        logger.info("通知地址: {}", notifyUrl);
        logger.info("========================");
        
        AlipayTradeAppPayResponse response = getAlipayClient().sdkExecute(alipayRequest);
        
        if (response.isSuccess()) {
            logger.info("支付宝APP支付创建成功: orderNo={}", request.getOrderNo());
            
            PaymentResponse paymentResponse = new PaymentResponse();
            paymentResponse.setSuccess(true);
            paymentResponse.setOrderNo(request.getOrderNo());
            paymentResponse.setPaymentUrl(response.getBody()); // 返回SDK调用字符串
            paymentResponse.setMessage("订单创建成功");
            return paymentResponse;
        } else {
            logger.error("支付宝APP支付创建失败: orderNo={}, code={}, msg={}", 
                        request.getOrderNo(), response.getCode(), response.getMsg());
            return createErrorResponse(request.getOrderNo(), response.getMsg());
        }
    }
    
    /**
     * 扫码支付 (alipay.trade.precreate)
     */
    private PaymentResponse createQrPayment(PaymentRequest request) throws AlipayApiException {
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setOutTradeNo(request.getOrderNo());
        model.setTotalAmount(request.getAmount().setScale(2).toString());
        model.setSubject(request.getSubject());
        model.setBody(request.getBody());
        model.setTimeoutExpress("30m");
        
        AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
        alipayRequest.setBizModel(model);
        String notifyUrl = aliPayProperties.getDomain() + "/api/forum/payment/alipay/notify";
        alipayRequest.setNotifyUrl(notifyUrl);
        
        // 打印调用参数
        logger.info("=== 支付宝扫码支付参数 ===");
        logger.info("订单号: {}", request.getOrderNo());
        logger.info("金额: {}", model.getTotalAmount());
        logger.info("标题: {}", model.getSubject());
        logger.info("描述: {}", model.getBody());
        logger.info("超时时间: {}", model.getTimeoutExpress());
        logger.info("通知地址: {}", notifyUrl);
        logger.info("========================");
        
        AlipayTradePrecreateResponse response = getAlipayClient().execute(alipayRequest);
        
        if (response.isSuccess() && StringUtils.hasText(response.getQrCode())) {
            logger.info("支付宝扫码支付创建成功: orderNo={}, qrCode={}", 
                       request.getOrderNo(), response.getQrCode());
            
            PaymentResponse paymentResponse = new PaymentResponse();
            paymentResponse.setSuccess(true);
            paymentResponse.setOrderNo(request.getOrderNo());
            paymentResponse.setPaymentUrl(response.getQrCode());
            paymentResponse.setThirdPartyOrderNo(response.getOutTradeNo());
            paymentResponse.setMessage("订单创建成功");
            return paymentResponse;
        } else {
            logger.error("支付宝扫码支付创建失败: orderNo={}, subCode={}, subMsg={}", 
                        request.getOrderNo(), response.getSubCode(), response.getSubMsg());
            return createErrorResponse(request.getOrderNo(), response.getSubMsg());
        }
    }
    
    /**
     * 创建错误响应
     */
    private PaymentResponse createErrorResponse(String orderNo, String message) {
        PaymentResponse response = new PaymentResponse();
        response.setSuccess(false);
        response.setOrderNo(orderNo);
        response.setMessage(message);
        return response;
    }
    
    @Override
    public PaymentStatus queryPayment(String orderNo, String thirdPartyOrderNo) {
        try {
            logger.info("查询支付宝订单状态: orderNo={}", orderNo);
            
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo(orderNo);
            
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            request.setBizModel(model);
            
            AlipayTradeQueryResponse response = getAlipayClient().execute(request);
            
            if (response.isSuccess()) {
                logger.info("订单状态查询成功: orderNo={}, tradeStatus={}", orderNo, response.getTradeStatus());
                
                // 转换支付宝交易状态
                String tradeStatus = response.getTradeStatus();
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    return PaymentStatus.SUCCESS;
                } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                    return PaymentStatus.PENDING;
                } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                    return PaymentStatus.CLOSED;
                } else {
                    return PaymentStatus.FAILED;
                }
            } else {
                logger.warn("订单状态查询失败: orderNo={}, subCode={}, subMsg={}", 
                           orderNo, response.getSubCode(), response.getSubMsg());
                return PaymentStatus.FAILED;
            }
            
        } catch (AlipayApiException e) {
            logger.error("查询支付宝订单异常: orderNo={}", orderNo, e);
            return PaymentStatus.FAILED;
        }
    }
    
    @Override
    public boolean closePayment(String orderNo, String thirdPartyOrderNo) {
        try {
            logger.info("关闭支付宝订单: orderNo={}", orderNo);
            
            AlipayTradeCloseModel model = new AlipayTradeCloseModel();
            model.setOutTradeNo(orderNo);
            
            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            request.setBizModel(model);
            
            AlipayTradeCloseResponse response = getAlipayClient().execute(request);
            
            if (response.isSuccess()) {
                logger.info("支付宝订单关闭成功: orderNo={}", orderNo);
                return true;
            } else {
                logger.error("支付宝订单关闭失败: orderNo={}, subCode={}, subMsg={}", 
                            orderNo, response.getSubCode(), response.getSubMsg());
                return false;
            }
            
        } catch (AlipayApiException e) {
            logger.error("关闭支付宝订单异常: orderNo={}", orderNo, e);
            return false;
        }
    }
    
    /**
     * 转换参数Map: Map<String, String[]> -> Map<String, String>
     */
    private Map<String, String> convertParams(Map<String, String[]> parameterMap) {
        Map<String, String> params = new HashMap<>();
        if (parameterMap != null) {
            parameterMap.forEach((key, values) -> {
                if (values != null && values.length > 0) {
                    params.put(key, values[0]);
                }
            });
        }
        return params;
    }
    
    @Override
    public boolean verifyCallback(PaymentCallback callback) {
        try {
            Map<String, String> params = convertParams(callback.getCallbackParams());
            
            boolean result = AlipaySignature.rsaCheckV1(
                params,
                aliPayProperties.getPublicKey(),
                aliPayProperties.getCharset(),
                aliPayProperties.getSignType()
            );
            
            logger.info("支付宝回调签名验证: orderNo={}, result={}", callback.getOrderNo(), result);
            return result;
            
        } catch (AlipayApiException e) {
            logger.error("支付宝回调签名验证失败: orderNo={}", callback.getOrderNo(), e);
            return false;
        }
    }
    
    @Override
    public CallbackResult processCallback(PaymentCallback callback) {
        try {
            // 验证签名
            if (!verifyCallback(callback)) {
                return CallbackResult.failure("签名验证失败");
            }
            
            Map<String, String> params = convertParams(callback.getCallbackParams());
            String tradeStatus = params.get("trade_status");
            String outTradeNo = params.get("out_trade_no");
            
            // 转换状态
            PaymentStatus status;
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                status = PaymentStatus.SUCCESS;
            } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                status = PaymentStatus.CLOSED;
            } else {
                status = PaymentStatus.PENDING;
            }
            
            CallbackResult result = CallbackResult.success(outTradeNo, status);
            result.setThirdPartyTradeNo(params.get("trade_no"));
            
            logger.info("支付宝回调处理成功: orderNo={}, status={}", outTradeNo, status);
            return result;
            
        } catch (Exception e) {
            logger.error("处理支付宝回调异常: orderNo={}", callback.getOrderNo(), e);
            return CallbackResult.failure("回调处理异常: " + e.getMessage());
        }
    }
    
    @Override
    public boolean isConfigured() {
        try {
            return aliPayProperties != null &&
                   aliPayProperties.getAppId() != null &&
                   aliPayProperties.getPrivateKey() != null &&
                   aliPayProperties.getPublicKey() != null &&
                   aliPayProperties.getServerUrl() != null;
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public Map<String, String> getConfigInfo() {
        Map<String, String> info = new HashMap<>();
        info.put("providerId", PROVIDER_ID);
        info.put("providerName", PROVIDER_NAME);
        info.put("appId", aliPayProperties.getAppId());
        info.put("serverUrl", aliPayProperties.getServerUrl());
        info.put("configured", String.valueOf(isConfigured()));
        return info;
    }
}
